package services

import (
	"context"
	"errors"
	"time"

	"github.com/golang-jwt/jwt/v4"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"

	"zwai-app/config"
	"zwai-app/db"
	"zwai-app/models"
)

var ErrInvalidCredentials = errors.New("invalid account or password")

// ErrInvalidToken 表示 Token 无效
var ErrInvalidToken = errors.New("invalid token")

// Claims 自定义 JWT 信息
type Claims struct {
	UserID string `json:"userId"`
	jwt.RegisteredClaims
}

// Login 校验账号密码，生成并返回 JWT
func Login(ctx context.Context, account, password string, cfg config.Config) (string, error) {
	coll := db.Client.Database(db.DBName).Collection("User")

	// 1) 校验账号和密码
	var u models.User
	err := coll.FindOne(ctx, bson.M{
		"account":  account,
		"password": password,
	}).Decode(&u)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return "", ErrInvalidCredentials
		}
		return "", err
	}

	// 2) 构造 JWT Claims
	now := time.Now()
	claims := Claims{
		UserID: u.ID.Hex(),
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(now.Add(24 * time.Hour)), // 24h 后过期
			IssuedAt:  jwt.NewNumericDate(now),
			Issuer:    "zwai-app",
			Subject:   u.ID.Hex(),
		},
	}

	// 3) 签发 Token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	signed, err := token.SignedString([]byte(cfg.JWTSecret))
	if err != nil {
		return "", err
	}

	return signed, nil
}

// ValidateToken 验证 JWT 并返回 userID
func ValidateToken(tokenStr string, cfg config.Config) (string, error) {
	token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(cfg.JWTSecret), nil
	})
	if err != nil || !token.Valid {
		return "", ErrInvalidToken
	}
	claims, ok := token.Claims.(*Claims)
	if !ok {
		return "", ErrInvalidToken
	}
	return claims.UserID, nil
}
